from fastapi import FastAPI, HTTPException, Depends, Cookie, Header, Response
from fastapi.middleware.cors import CORSMiddleware
from sse_starlette.sse import EventSourceResponse
from typing import List, Optional, Dict, Any
import asyncio
import json
from app.models.clipboard import ClipboardItem
from app.utils.auth import verify_password
from app.utils.redis import RedisStore

app = FastAPI()

# 配置 CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:3000",
        "https://clipboard.mlover.site",
        "https://clipboard-sync.vercel.app"
    ],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 存储 SSE 客户端
clients = []

@app.post("/api/login")
async def login(password: dict, response: Response):
    """登录验证"""
    print(f"Received login request with password: {password}")
    if not password.get("password"):
        raise HTTPException(status_code=400, detail="密码不能为空")
    
    if verify_password(password["password"]):
        response.set_cookie(
            key="auth",
            value=password["password"],
            httponly=True,
            samesite="lax",
            secure=True  # 生产环境设为 True
        )
        return {"success": True}
    else:
        raise HTTPException(status_code=401, detail="密码错误")

def get_auth(auth: Optional[str] = Cookie(None)) -> bool:
    """验证用户是否已登录"""
    if not auth:
        raise HTTPException(status_code=401, detail="未登录")
    if not verify_password(auth):
        raise HTTPException(status_code=401, detail="登录已过期")
    return True

@app.post("/api/clipboard/upload")
async def upload_clipboard(item: ClipboardItem, _: bool = Depends(get_auth)):
    """上传剪贴板内容"""
    RedisStore.save_clipboard(item.model_dump())
    # 通知所有订阅的客户端
    for client in clients:
        await client.put(item.model_dump())
    return item

@app.get("/api/clipboard/history")
async def get_history(_: bool = Depends(get_auth)) -> List[dict]:
    """获取剪贴板历史"""
    return RedisStore.get_clipboard_history()

@app.delete("/api/clipboard/delete/{item_id}")
async def delete_clipboard(item_id: str, _: bool = Depends(get_auth)):
    """删除剪贴板内容"""
    RedisStore.delete_clipboard(item_id)
    return {"success": True}

@app.get("/api/clipboard/subscribe")
async def subscribe(_: bool = Depends(get_auth)):
    """订阅剪贴板更新"""
    client = asyncio.Queue()
    clients.append(client)
    
    async def event_generator():
        try:
            while True:
                data = await client.get()
                yield {
                    "event": "update",
                    "data": json.dumps(data)
                }
        except asyncio.CancelledError:
            clients.remove(client)
    
    return EventSourceResponse(event_generator())

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8080) 